package com.xlongwei.accounts.service;

import java.time.LocalDate;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.annotation.TranAnno;
import org.noear.solon.data.tran.TranUtils;
import org.noear.solon.test.SolonTest;
import com.xlongwei.accounts.App;

import features.SqlTest;

@SolonTest(App.class)
public class RecordServiceTest {
    @Inject
    RecordService recordService;
    @Inject
    AccountService accountService;

    @Test
    public void income() throws Throwable {
        Assertions.assertThrows(Throwable.class, () -> {
            TranUtils.execute(new TranAnno(), () -> {
                try {
                    recordService.income(1, 1, 100, 1, 0, LocalDate.now(), null);
                    Map<Integer, Long> balances = accountService.balances(1);
                    Assertions.assertEquals(100, balances.get(1));
                    recordService.income(1, 1, 100, 1, 0, LocalDate.now(), "继续");
                    balances = accountService.balances(1);
                    Assertions.assertEquals(200, balances.get(1));
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                System.err.println("rollback");
                throw new RuntimeException("rollback");
            });
        });
    }

    @Test
    public void outcome() throws Throwable {
        Assertions.assertThrows(Throwable.class, () -> {
            TranUtils.execute(new TranAnno(), () -> {
                try {
                    recordService.income(1, 1, 200, 1, 0, LocalDate.now(), null);
                    Map<Integer, Long> balances = accountService.balances(1);
                    Assertions.assertEquals(200, balances.get(1));
                    recordService.outcome(1, 2, 100, 1, 0, LocalDate.now(), "继续");
                    balances = accountService.balances(1);
                    Assertions.assertEquals(100, balances.get(1));
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                System.err.println("rollback");
                throw new RuntimeException("rollback");
            });
        });
    }

    @Test
    public void transfer() throws Throwable {
        Assertions.assertThrows(Throwable.class, () -> {
            TranUtils.execute(new TranAnno(), () -> {
                try {
                    recordService.income(1, 1, 200, 1, 0, LocalDate.now(), null);
                    Map<Integer, Long> balances = accountService.balances(1);
                    Assertions.assertEquals(200, balances.get(1));
                    recordService.transfer(1, 3, 100, 1, 2, 1, LocalDate.now(), "继续");
                    balances = accountService.balances(1);
                    Assertions.assertEquals(100, balances.get(1));
                    Assertions.assertEquals(100, balances.get(2));
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                System.err.println("rollback");
                throw new RuntimeException("rollback");
            });
        });
    }

    @Test
    public void balances() throws Throwable {
        SqlTest.testAndRollback(() -> {
            Integer userid = 1, ledgerid = 1, accountid_in = 1, memberid = 1;
            LocalDate day = LocalDate.now();
            recordService.income(userid, ledgerid, Integer.MAX_VALUE, accountid_in, memberid, day, null);
            Assertions.assertEquals(Integer.MAX_VALUE, accountService.balances(userid).get(userid));
            recordService.income(userid, ledgerid, Integer.MAX_VALUE, accountid_in, memberid, day, null);
            Assertions.assertEquals(Integer.MAX_VALUE * 2L, accountService.balances(userid).get(userid));
            recordService.outcome(userid, 2, Integer.MAX_VALUE, accountid_in, memberid, day, null);
            Assertions.assertEquals(Integer.MAX_VALUE, accountService.balances(userid).get(userid));
            recordService.outcome(userid, 2, Integer.MAX_VALUE, accountid_in, memberid, day, null);
            Assertions.assertEquals(0, accountService.balances(userid).get(userid));
        });
    }
}
